1. Technical Field
The present invention is directed to an improved data processing system and, in particular, an improved mechanism providing a new Permission for methods that perform callback operations.
2. Description of Related Art
In Java Development Kit (JDK) version 1.1, local applications and remote programs signed by a trusted entity were generally granted full access to vital system resources, such as the file system. Unsigned remote programs, or remote programs signed by untrusted entities, could access only limited resources. A SecurityManager was responsible for determining which resource accesses were allowed.
In the Java 2 Software Development Kit (SDK), the security architecture is policy-based and allows for fine-grained access control. In Java 2 SDK, when code is loaded by the ClassLoader, it is assigned to a ProtectionDomain that contains a collection of Permissions based on the security policy currently in effect. Each Permission specifies a permitted access to a particular resource, such as “read” and “write” access to a specified file or directory, or “connect” access to a given host and port. The security policy specifying which Permissions are available for code from various signers and/or locations can be initialized from an external configurable policy file. Unless a Permission is explicitly granted to code, that code cannot access the resource that is protected by that Permission. These concepts of Permission and policy enable the Java 2 SDK to offer fine-grained, highly configurable, flexible, and extensible access control. Such access control can be specified for all Java code including but not limited to applications, applets, Java beans, and servlets.
The Java 2 security architecture imposes the constraint that whenever access to a protected resource is attempted, each class in the execution stack is checked for the required Permission to access that resource. This Permission checking is performed by the method java.security.AccessController.checkPermission( ). The security policy would be ineffective if code with no Permissions were able to invoke code with more Permissions and by doing so, access protected resources that it should not access by virtue of its own ProtectionDomain.
It can be seen that with large programs having many methods and classes, it may be very cumbersome to identify all of the Permissions that are being used and to which classes the Permissions should be granted. The Java 2 security architecture does provide some mechanisms for granting Permissions without having to explicitly grant each and every Permission that would be necessary to ensure that a piece of code can work with all protected resources.
For example, Java 2 SDK provides the AllPermission Permission type that provides a means by which all Permissions are granted to a class. In practice, AllPermission grants code the ability to run with security disabled. The security problems associated with using such a Permission indiscriminately are apparent. This Permission is intended be used only during testing, or in extremely rare cases where a program or library is completely trusted, and adding the necessary Permissions to the policy is prohibitively cumbersome.
Another tool provided through the Java 2 SDK is the AccessController.doPrivileged( ) method. Calling this method allows for the checking of Permissions to access a protected resource to be halted at the method that calls doPrivileged( ). In this way, the method calls higher in the thread stack than the method calling doPrivileged( ) are implicitly granted the requisite Permissions to access the protected resource. This method call is intended to be used in situations where forcing the requirement that all method calls in the thread stack have the expressly granted Permission to access the protected resource is impractical or undesirable, such as with client code that calls Application Program Interface (API) code.
A problem arises with the checking of Permissions when a “callback” in the code is encountered. For example, assume that there are two classes “A” and “B”. Further, there is a method in “A” called “M1”, and a method in “B” called “M2”. If “M2” obtains a reference to an instance of “A” (for example, through a method parameter, a return value from a method invocation, or a field), and calls M1 on that instance, then the location where this call occurs is called a callback.
If the Java 2 authorization system, implemented by AccessController.checkPermission( ), is called as a result of M2 calling M1, a problem arises because all of the active methods in the current thread, including M2, need to be authorized for the privileged operation. If M1 or any of the methods subsequently called and appearing in the thread stack do not make a call to AccessController.doPrivileged( ), then class “B” will be required to be authorized for the privileged operation, which means that it will have to have the required Permission specifically granted to it.
The most common case where this occurs is in general-purpose library code as is found in the Java runtime, which can be called by any client code. In particular, the client code calling library code can pass parameters to the library code methods. These same parameters can then be used by the library code as receivers for method invocations. In general, the behavior of each of those client code methods is a priori unknown (unless the declared type of the parameter is final, which means that it cannot be overwritten) because it depends on the client code implementation. As a result, it is not possible to know a priori which Permissions will be needed by the parameters passed to the library code.
The current solution is to give class “B” in the library the Java 2 AllPermission Permission, which is equivalent to the Permission to perform any Java 2 privileged operation, so that when a callback occurs, all methods in “B” will be authorized. In this way, when Java 2 authorization calls are made as a result of a callback, the authorization will succeed. However, one of the effects of allocating AllPermission to class “B” is that it may result in a security hole because class “B” becomes over privileged, violating the “Principle of Least Privilege”.
Thus, it would be beneficial to have an apparatus and method for implementing a new Permission type that allows for callback methods to be authorized using the Java 2 authorization system while not over privileging other code and thereby creating security holes.